﻿namespace FiftyOne.Foundation.Mobile.Detection.Wurfl
{
    using FiftyOne;
    using FiftyOne.Foundation.Mobile.Detection;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl.Configuration;
    using System;
    using System.IO;
    using System.Net;
    using System.Security;
    using System.Threading;
    using System.Web;

    internal class WurflNewDevice
    {
        private static bool _enabled = false;
        private static Uri _newDevicesUrl = null;

        static WurflNewDevice()
        {
            if (Uri.TryCreate(Manager.NewDevicesURL, UriKind.RelativeOrAbsolute, out _newDevicesUrl))
            {
                _enabled = true;
            }
        }

        private static void ProcessNewDevice(object sender)
        {
            NewDeviceData newDevice = sender as NewDeviceData;
            if (newDevice != null)
            {
                try
                {
                    if (!(string.IsNullOrEmpty(Manager.NewDevicesURL) || string.IsNullOrEmpty(newDevice.Content)))
                    {
                        RecordToURL(newDevice);
                    }
                }
                catch (SecurityException)
                {
                    EventLog.Warn(string.Format("Insufficient permission to send new device information to '{0}'.", _newDevicesUrl));
                    _enabled = false;
                }
                catch (WebException exception)
                {
                    try
                    {
                        if (!newDevice.IsLocal)
                        {
                            EventLog.Warn(string.Format("Could not write device information for useragent '{0}' to URL '{1}'. Exception '{2}'", newDevice.UserAgent, _newDevicesUrl.ToString(), exception.Message));
                        }
                        else
                        {
                            EventLog.Debug(string.Format("Could not write device information for useragent '{0}' to URL '{1}'. Exception '{2}'", newDevice.UserAgent, _newDevicesUrl.ToString(), exception.Message));
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }

        internal static void RecordNewDevice(HttpRequest request)
        {
            NewDeviceData state = new NewDeviceData(request);
            if (!state.Ignore)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(WurflNewDevice.ProcessNewDevice), state);
            }
        }

        private static void RecordToURL(NewDeviceData newDevice)
        {
            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(_newDevicesUrl);
            request.Timeout = 0x1388;
            request.Method = "POST";
            StreamWriter writer = new StreamWriter(request.GetRequestStream());
            writer.Write(newDevice.Content);
            writer.Flush();
            writer.Close();
            request.GetResponse();
        }

        protected internal static bool Enabled
        {
            get
            {
                return _enabled;
            }
        }

        internal class NewDeviceData
        {
            private string _content = null;
            private bool _ignore = false;
            private bool _isLocal = false;
            private static NewDeviceDetail _newDeviceDetail = Manager.NewDeviceDetail;
            private string _userAgent = null;

            internal NewDeviceData(HttpRequest request)
            {
                this._content = RequestHelper.GetContent(request, _newDeviceDetail == NewDeviceDetail.Maximum);
                this._userAgent = Provider.GetUserAgent(request);
                this._isLocal = request.IsLocal;
                this._ignore = request.Headers["51D"] != null;
            }

            internal string Content
            {
                get
                {
                    return this._content;
                }
            }

            internal bool Ignore
            {
                get
                {
                    return this._ignore;
                }
            }

            internal bool IsLocal
            {
                get
                {
                    return this._isLocal;
                }
            }

            internal string UserAgent
            {
                get
                {
                    return this._userAgent;
                }
            }
        }
    }
}

